package distanceMatrix;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Hashtable;

import tools.utils.DoubleMatrix;

public class DistanceMatrix {

	DoubleMatrix values;
	Hashtable<String, Integer> names2nr;
	Hashtable<Integer, String> nr2names;
	ArrayList<String> names;
	
	public DistanceMatrix() {
		names2nr=new Hashtable<String, Integer>();
		nr2names=new Hashtable<Integer, String>();
		names=new ArrayList<String>();
	}
	public DistanceMatrix(int size){
		this();
		values=new DoubleMatrix(size,size);
	}
	/**
	 * 
	 * @param format - extended_water_needle
	 * @param args
	 * @throws Exception
	 */
	public DistanceMatrix(String format, String... args)throws Exception{
		this();
		if(format.equals("extended_water_needle")&&args.length>0){
			this.build_extended_water_needle(args[0]);
		}
	}
	/**
	 * 
	 * @param file on the format (tab-separated): qname/tname/matrix/gap_penalty/extend_penalty/length/identity/similarity/gaps/score
	 * @throws Exception
	 */
	private void build_extended_water_needle(String file)throws Exception{
		int missingPositions=0,position=-1;
		Hashtable<String, Hashtable<String, double[]>> tmpMatrix=new Hashtable<String, Hashtable<String,double[]>>(); //double[]={identity,score}
		BufferedReader in=new BufferedReader(new FileReader(file));
		for(String s=in.readLine();s!=null;s=in.readLine()){
			String[] l=s.split("\t");
			if(l.length==10){
				if(!names.contains(l[0])){
					names2nr.put(l[0], ++position);
					nr2names.put(position, l[0]);
					names.add(l[0]);
					tmpMatrix.put(l[0], new Hashtable<String, double[]>());
				}
				if(!names.contains(l[1])){
					names2nr.put(l[1], ++position);
					nr2names.put(position, l[1]);
					names.add(l[1]);
					tmpMatrix.put(l[1], new Hashtable<String, double[]>());
				}
				double[] tmp=new double[]{Double.parseDouble(l[6]),Double.parseDouble(l[9])};
//				if(l[0].equals("66878")&&l[1].equals("GPR26")){
//					System.out.println(s);
//					System.out.println("identity: "+tmp[0]);
//					System.out.println("score: "+tmp[1]);
//				}
				tmpMatrix.get(l[0]).put(l[1], tmp);
				tmpMatrix.get(l[1]).put(l[0], tmp);
			}
		}
		int size=position+1;
		values=new DoubleMatrix(size,size);
		for(int i=0;i<size;i++){
			Hashtable<String, double[]> tmp=tmpMatrix.get(nr2names.get(i));
			for(int j=0;j<i;j++){
				if(tmp.containsKey(nr2names.get(j))){
					values.set(i, j, tmp.get(nr2names.get(j))[0]);
				}else{
					missingPositions++;
					values.set(i, j, 0);
				}
			}
			for(int j=i;j<size;j++){
				if(tmp.containsKey(nr2names.get(j))){
					values.set(i, j, tmp.get(nr2names.get(j))[1]);
				}else{
					missingPositions++;
					values.set(i, j, 0);
				}
			}
		}
//		System.out.println("#Missing positions: "+missingPositions);
	}
	
	public double getIdentity(int s1,int s2)throws Exception{
		if(s1==s2){
			return 100.0;
		}else if(s1>s2){
			return values.get(s1, s2);
		}else{
			return values.get(s2, s1);
		}
	}
	public double getScore(int s1,int s2)throws Exception{
		if(s1<=s2){
			return values.get(s1, s2);
		}else{
			return values.get(s2, s1);
		}
	}
	public double getIdentity(String s1,String s2)throws Exception{
		return getIdentity(names2nr.get(s1), names2nr.get(s2));
	}
	public double getScore(String s1,String s2)throws Exception{
		return getScore(names2nr.get(s1),names2nr.get(s2));
	}
	public ArrayList<String> getNames(){
		return names;
	}
}

